package com.seed.uaa.web.organization;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import com.seed.core.annotation.BelongsTo;
import com.seed.core.annotation.Col;
import com.seed.core.annotation.Habtm;
import com.seed.core.annotation.HasMany;
import com.seed.core.enumeration.Cascade;
import com.seed.core.enumeration.ColumnType;
import com.seed.core.enumeration.YesNo;
import com.seed.uaa.web.role.Role;
import com.seed.uaa.web.user.User;
import io.swagger.v3.oas.annotations.media.Schema;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

/**
 * mysql 查询父组织， 如： 子组织编号为 3-12-5
 * select SUBSTR(`code`, 1, LENGTH(`code`) - LENGTH(SUBSTRING_INDEX(REVERSE(`code`),'-',1)) - 1) parent_code
 * from uaa_organization
 * WHERE `code` = '3-12-5';
 *
 * mysql 查询子组织， 如：父组织编号为 3,
 * select `code` from uaa_organization
 * WHERE SUBSTR(`code`, 1, LENGTH(`code`) - LENGTH(SUBSTRING_INDEX(REVERSE(`code`),'-',1)) - 1) = '3';
 */
@Schema(description = "组织")
@Table(value = "uaa_organization")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Organization {
    @Id
    @Schema(title = "ID")
    private String id;

    @Schema(title = "编码")
    @Col(required = true, unique = true)
    private String code;

    @Schema(title = "名称")
    private String name;

    @Schema(title = "上级组织")
    private String parentId;

    @Schema(title = "负责人")
    private String managerId;

    @Schema(title = "截止日期")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private LocalDate expireDate;

    @Schema(title = "是否可用", description = "如果为no,则连下级用户也不能登录，用于主动停止使用系统")
    private YesNo usable;

    @Schema(title = "是否可登录", description = "如果为no,则连下级用户也不能登录，用于被动停止使用系统")
    private YesNo loginable;

    @Schema(title = "是否启用", description = "如果为no,则自己不能登录，不影响下级")
    private YesNo enable;

    @Schema(title = "原因", description = "账号不能登录系统的原因")
    private String reason;

    @Schema(title = "编制", description = "该组织下最多可以有多少个子组织")
    private Integer clerkSize;

    @Schema(title = "访问权限")
    @Col(type = ColumnType.TEXT, length = 2048)
    private String actions;

    @Schema(title = "数据权限")
    @Col(type = ColumnType.TEXT, length = 2048)
    private String datas;

    @Schema(title = "字段权限")
    @Col(type = ColumnType.TEXT, length = 2048)
    private String fields;

    @Schema(title = "所属租户")
    private String tenantId;

    @Schema(title = "创建时间")
    @Column(onInsertValue = "now()")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createdAt;

    @Schema(title = "创建时间")
    @Column(onInsertValue = "now()", onUpdateValue = "now()")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updatedAt;

    @Schema(title = "删除时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime deletedAt;

    @Schema(title = "版本号")
    @Column(version = true)
    private Long version;

    @Schema(title = "负责人")
    @Column(ignore = true)
    @BelongsTo(selfColumn = "managerId", comment = "组织的负责人")
    private User manager;

    @Schema(title = "角色")
    @Column(ignore = true)
    @Habtm(through = OrganizationRole.class, label = "组织角色", comment = "组织拥有的角色", cascade = Cascade.force)
    private List<Role> roles;

    @Schema(title = "上级")
    @Column(ignore = true)
    @BelongsTo(label = "上级组织")
    private Organization parent;

    @Schema(title = "下级")
    @Column(ignore = true)
    @HasMany(targetColumn = "parentId", label = "下级组织", cascade = Cascade.check )
    private List<Organization> children;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getParentId() {
        return parentId;
    }

    public void setParentId(String parentId) {
        this.parentId = parentId;
    }

    public String getManagerId() {
        return managerId;
    }

    public void setManagerId(String managerId) {
        this.managerId = managerId;
    }

    public LocalDate getExpireDate() {
        return expireDate;
    }

    public void setExpireDate(LocalDate expireDate) {
        this.expireDate = expireDate;
    }

    public YesNo getUsable() {
        return usable;
    }

    public void setUsable(YesNo usable) {
        this.usable = usable;
    }

    public YesNo getLoginable() {
        return loginable;
    }

    public void setLoginable(YesNo loginable) {
        this.loginable = loginable;
    }

    public YesNo getEnable() {
        return enable;
    }

    public void setEnable(YesNo enable) {
        this.enable = enable;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public Integer getClerkSize() {
        return clerkSize;
    }

    public void setClerkSize(Integer clerkSize) {
        this.clerkSize = clerkSize;
    }

    public String getActions() {
        return actions;
    }

    public void setActions(String actions) {
        this.actions = actions;
    }

    public String getDatas() {
        return datas;
    }

    public void setDatas(String datas) {
        this.datas = datas;
    }

    public String getFields() {
        return fields;
    }

    public void setFields(String fields) {
        this.fields = fields;
    }

    public String getTenantId() {
        return tenantId;
    }

    public void setTenantId(String tenantId) {
        this.tenantId = tenantId;
    }

    public LocalDateTime getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }

    public LocalDateTime getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(LocalDateTime updatedAt) {
        this.updatedAt = updatedAt;
    }

    public LocalDateTime getDeletedAt() {
        return deletedAt;
    }

    public void setDeletedAt(LocalDateTime deletedAt) {
        this.deletedAt = deletedAt;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    public User getManager() {
        return manager;
    }

    public void setManager(User manager) {
        this.manager = manager;
    }

    public Organization getParent() {
        return parent;
    }

    public void setParent(Organization parent) {
        this.parent = parent;
    }

    public List<Organization> getChildren() {
        return children;
    }

    public void setChildren(List<Organization> children) {
        this.children = children;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }
}
